<?php
/*
 * kernel/handlers/database/db.mssql.php
 *
 * This code is distributed and used under the GNU GPL v2 License,
 * please, read file LICENSE, which is situated in root directory,
 * or in "LICENSE" directory with most acceptable translation for you
 *
 * Microsoft SQL Server support
 *
 * Copyright (c) Taras Kudla, 2010
 */

# status: it doesn't works mostly

class gDatabaseMssql extends gKernel implements gDatabaseConnector
  {
    private $rConnection = null;

    private $DefaultEngine = "MyISAM";

    private $DefaultCharset = "utf8";

    public function init(){

        if (!extension_loaded("mssql"))
            $this->core->error("DBO_MSSQL", "extension \"mssql\" not loaded... Cannot work ....");
            return false;}

    public function connect($serv, $db, $user, $passwd)
      {

        if ($this->core->dbo->UsePersistent==true)
          { 
            $this->rConnection = @mssql_pconnect($serv, $user, $passwd);

          }
        else
          {
            $this->rConnection = @mssql_connect($serv, $user, $passwd);
          }

        if (!is_resource($this->rConnection))
          {
            $this->core->error("DBO_DRIVER_CONNECT", "CANNOT CONNECT TO THE DATABASE SERVER. CHECK PARAMETERS PLEASE.");
            return false;

          }
        else
          {
            if(!mssql_select_db($db, $this->rConnection)){
            	 $this->core->error("DBO_DRIVER_CONNECT", "CANNOT SELECT DATABASE ON MSSQL SERVER. CHECK PARAMETERS PLEASE.");
            	 return false;
            }

            $this->direct("set names utf8;");

          }
      }

    public function disconnect()
      {
        /*
         * Error in this function, segmentation fault with zend optimizer, if mysql_close previously called
         */

        if (is_resource($this->rConnection))
          {
            mssql_close($this->rConnection);
          }

      }

    public function select($table, $fields = "*", $sql = null, $type = _RESULT_ASSOC)
      {
        $sql = "select " . $fields . " from " . $table . " " . $sql;

        $q = @mssql_query($sql, $this->rConnection);

        if ($q == false)
          {
            $this->core->error("DBO_DRIVER_SELECT", "<br>&nbsp;<b>" . $sql . "</b>");
			return false;
          }


        switch ($type)
        {

            case _RESULT_ASSOC:
                return $this->sqlToAssoc($q);
                break;

            case _RESULT_LIST:
                return $this->sqlToList($q, $fields);
                break;

            case _RESULT_BOOL:
                return ((bool) mysql_num_rows($q));
                break;

            case _RESULT_PAIRS:
                return $this->sqlToPairs($q);
                break;

            case _RESULT_ROW:
                return $this->sqlToRow($q);
                break;
	    
	    case _RESULT_SINGLE:
	    	return $this->sqlToSingle($q);
	    	break;	    
	    	
            default:
                return $this->sqlToAssoc($q);

        }


      }

    private function &sqlToList(&$q, $fields)
      {
        if (preg_match("/[,]/", $fields, $null))
          {
            $this->core->error("DBO_DRIVER_SELECT", "Error in results ordering as LIST. Field should be without comas.");
            return false;
          }

        $a = array();

        $i = 0;

        while ($i < mysql_num_rows($q))
          {
            $_ = mysql_fetch_row($q);

            $a[] = $_[0];

            $i++;

          }		  
		mssql_free_result($q);

        return $a;
      }
      
    // single result
    private function sqlToSingle(&$q){
    	if( mysql_num_rows($q) == 1 && mysql_num_fiedls($q)== 1 ){
    		$q=mssql_fetch_row($q);
			mssql_free_result($q);
    		return $q[0];
    	}   
    	return null; 
    }

    // key->value pairs
    private function & sqlToRow(&$q)
      {
        if (mssql_num_rows($q) == 0)
            return array();
		
        $result=mssql_fetch_assoc($q);
		mssql_free_result($q);
		return $result;
      }


    private function &sqlToPairs(&$q)
      {
        $array = array();

        if (mssql_num_fields($q) != 2)
          {
            $this->core->error("DBO", "Cannot build pairs for result. Fields number must be 2");
            return false;
          }
        $i = 0;
        while ($i < mssql_num_rows($q))
          {
            $tmp = 0;

            $f = mssql_fetch_row($q);

            $array[$f[0]] = $f[1];

            $i++;

          }
		mssql_free_result($q);

        return $array;
      }


    private function &sqlToAssoc(&$q)
      {
        $array = array();

        for ($i = 0; $i < mssql_num_rows($q); $i++)
          {
            $array[$i] = mssql_fetch_assoc($q);

          }
		mssql_free_result($q);
        return $array;

      }




    public function insert($table, array $data)
      {
        if (!is_array($data) || count($data) < 1)
          {
            return false;
          }

        $a   = null;
        $b   = null;
        $c   = null;
        $i   = 1;
        $num = count($data);

        foreach ($data as $k => $v)
          {
            $ex = explode("|", $k);

            if (count($ex) == 2 && $ex[1] == "F")
              {
                $a .= "`" . $ex[0] . "`" . ($i < $num ? "," : null);

                $b .= "" . $v . "" . ($i < $num ? "," : null);

              }
            else
              {
                $a .= "`" . $k . "`" . ($i < $num ? "," : null);

                $b .= "'" . $v . "'" . ($i < $num ? "," : null);
              }

            $i++;
          }

        $sql = "insert into `" . $table . "` (" . $a . ") values (" . $b . ")";

        $q = @mssql_query($sql, $this->rConnection);

        if ($q == false)
          {
            $this->core->error("DBO_DRIVER_INSERT", "$sql");
            return false;
          }

        return true;

      }

    public function update($table, $sql)
      {
        $sql = "update " . $table . " " . $sql;

        $q = @mssql_query($sql, $this->rConnection);

        if ($q == false)
          {
            $this->core->error("DBO_DRIVER_UPDATE", "$sql");
            return false;
          }
		mssql_free_result($q);

        return true;

      }
    public function delete($table, $sql)
      {
        $sql = "delete from " . $table . " " . $sql;

        $q = @mssql_query($sql, $this->rConnection);

        if ($q == false)
          {
            $this->core->error("DBO_DRIVER_DELETE", "$sql");
          }

        return $q;
      }
    public function direct($sql)
      {
        $q = @mssql_query($sql, $this->rConnection);

        if ($q == false)
          {
            $this->core->error("DBO_DRIVER_DIRECT", "$sql");
            mssql_free_result($q);
			return false;
          }
			
        return $q;

      }

    public function version()
      {
      }

    public function createtable(table $map)
      {

      	list($name,$fields,$keys,$encoding,$engine) = $map->get();
        $pkeys =array();
      	foreach( $keys as $k=>$v ){
      		if( strtolower($v[0])=="primary") $pkeys[]=$v[1];
      	}
      	      	
      	$text = "create table $name ( ";
      	# fields processing      	
      	foreach( $fields as $k=>$v){
      		list($fname,$ftype,$fsize,$fdefault) = $v;
			if( $ftype=="int_auto" && !in_array($fname,$pkeys) ){
				$pkeys[]=$fname;
			}      		
      		$fresult = $this->type_def($ftype,$fsize);
      		$text .=($k==0?null:" ,")." $fname $fresult ".( !is_null($fdefault)?" default '".$fdefault."' ":" not null " )." ";
      	}
      	if( count($pkeys)>0){
      		$text .=", PRIMARY KEY ( ".implode(",",$pkeys)." ) ";
      	}      	
		$text = " ) ";
		
      	//$text .=" ) ENGINE=".(  is_null($engine)?$this->DefaultEngine:$engine)." ".
      	//( is_null($encoding)?" DEFAULT CHARSET='".$this->DefaultCharset:$encoding)."' COMMENT='Created with Azaria v".$this->core->GetVersion()."'; " ;    	
      	# text is ready for table execution
      	if( $map->droponexist){
      		$this->direct("drop table if exists `$name` ");
      	}    	
      	
      	$this->direct($text);  	
      	# keys processing
      	foreach( $keys as $k=>$v){
      		$query = null;
      		list($ktype,$kfield) = $v;
      		$keydata = null;      		
      		switch( strtolower($ktype) ){
      			//case "primary": $keydata = "PRIMARY KEY"; break;
      			case "index"  : $keydata = "INDEX"; break;
      			case "unique" : $keydata = "UNIQUE"; break;
      			//case "fulltext": $keydata = "FULLTEXT"; break;     			
      		}    		
      		if( !is_null($keydata)){
      			
      			$query = "ALTER TABLE $name ADD $keydata ( ".$kfield." ); ";
      			$this->direct($query);
      			
      		}
      	}
      	      	
	}
    
    public function droptable($table){
    	
    	$this->direct("drop table if exists `".$table."`");
    	
    	return true;
    }  
      

    private function type_def($type, $size = null)
      {
        $result = null;
        switch ($type)
        {
            case "int_auto":
                $result = "INT(" . ($size != null ? (int) $size : "11") . ") IDENTITY ";
                break;
            case "int":
                $result = "INT(" . ($size != null ? (int) $size : "11") . ") ";
                break;
            case "bigint":
                $result = "BIGINT(" . ($size != null ? (int) $size : "20") . ") ";
                break;
            case "char":
                $result = "VARCHAR(" . ($size != null ? (int) $size : "255") . ") ";
                break;
            case "date":
                $result = "SMALLDATETIME ";
                break;
            case "float":
            	$result = "FLOAT";
            	break;
            case "text":
                $result = "TEXT";
                break;
            case "datetime":
                $result = " DATETIME";
                break;
            default:
                "char(255)";
                break;

        }
        return $result;
      }
  }
?>
